package com.voicecomm.config;

import com.voicecomm.database.DatabaseConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.yaml.snakeyaml.Yaml;

import java.io.InputStream;
import java.util.Map;

/**
 * 应用程序配置管理类
 * 负责加载和管理应用程序的各种配置参数
 * 
 * @author VoiceComm Team
 * @version 1.0.0
 */
public class ApplicationConfig {
    
    private static final Logger logger = LoggerFactory.getLogger(ApplicationConfig.class);
    
    // 百度AI配置
    private String baiduAppId;
    private String baiduApiKey;
    private String baiduSecretKey;
    
    // 数据库配置
    private DatabaseConfig databaseConfig;
    
    // 音频处理配置
    private AudioConfig audioConfig;
    
    // 日志配置
    private LogConfig logConfig;

    // 台站配置
    private String myCallsign; // 我的固定呼号
    
    // 系统配置
    private boolean disableDatabase = false; // 数据库禁用开关
    
    /**
     * 默认构造函数
     */
    public ApplicationConfig() {
        loadDefaultConfig();
    }
    
    /**
     * 从YAML文件加载配置
     * 
     * @param configFile 配置文件路径
     */
    public void loadFromYaml(String configFile) {
        try (InputStream inputStream = getClass().getClassLoader().getResourceAsStream(configFile)) {
            if (inputStream == null) {
                logger.warn("配置文件 {} 未找到，使用默认配置", configFile);
                return;
            }
            
            Yaml yaml = new Yaml();
            Map<String, Object> config = yaml.load(inputStream);
            
            loadBaiduConfig((Map<String, Object>) config.get("baidu"));
            loadDatabaseConfig((Map<String, Object>) config.get("database"));
            loadAudioConfig((Map<String, Object>) config.get("audio"));
            loadLogConfig((Map<String, Object>) config.get("log"));
            loadStationConfig((Map<String, Object>) config.get("station"));
            loadSystemConfig((Map<String, Object>) config.get("system"));
            
            logger.info("配置文件 {} 加载成功", configFile);
            
        } catch (Exception e) {
            logger.error("加载配置文件失败: {}", configFile, e);
            throw new RuntimeException("配置加载失败", e);
        }
    }
    
    /**
     * 加载默认配置
     */
    private void loadDefaultConfig() {
        // 百度AI默认配置（需要用户设置）
        this.baiduAppId = System.getProperty("baidu.app.id", "");
        this.baiduApiKey = System.getProperty("baidu.api.key", "");
        this.baiduSecretKey = System.getProperty("baidu.secret.key", "");
        
        // 数据库默认配置
        this.databaseConfig = DatabaseConfig.createLocalMySQLConfig(
            "voice_comm_logs", "root", "password");
        
        // 音频处理默认配置
        this.audioConfig = new AudioConfig();
        
        // 日志默认配置
        this.logConfig = new LogConfig();
        // 台站默认配置
        this.myCallsign = System.getProperty("station.my_callsign", "");
        
        // 系统默认配置
        this.disableDatabase = Boolean.parseBoolean(System.getProperty("system.disable_database", "false"));
        
        logger.info("默认配置加载完成");
    }
    
    /**
     * 加载百度AI配置
     */
    private void loadBaiduConfig(Map<String, Object> baiduConfig) {
        if (baiduConfig != null) {
            this.baiduAppId = (String) baiduConfig.getOrDefault("app_id", this.baiduAppId);
            this.baiduApiKey = (String) baiduConfig.getOrDefault("api_key", this.baiduApiKey);
            this.baiduSecretKey = (String) baiduConfig.getOrDefault("secret_key", this.baiduSecretKey);
        }
    }
    
    /**
     * 加载数据库配置
     */
    private void loadDatabaseConfig(Map<String, Object> databaseConfig) {
        if (databaseConfig != null) {
            String host = (String) databaseConfig.getOrDefault("host", "localhost");
            int port = (Integer) databaseConfig.getOrDefault("port", 3306);
            String database = (String) databaseConfig.getOrDefault("database", "voice_comm_logs");
            String username = (String) databaseConfig.getOrDefault("username", "root");
            String password = (String) databaseConfig.getOrDefault("password", "password");
            
            this.databaseConfig = DatabaseConfig.createMySQLConfig(host, port, database, username, password);
            
            // 连接池配置
            if (databaseConfig.containsKey("pool")) {
                Map<String, Object> poolConfig = (Map<String, Object>) databaseConfig.get("pool");
                this.databaseConfig.setMaxPoolSize((Integer) poolConfig.getOrDefault("max_pool_size", 10));
                this.databaseConfig.setMinIdle((Integer) poolConfig.getOrDefault("min_idle", 2));
                this.databaseConfig.setConnectionTimeout(Long.parseLong((String)poolConfig.getOrDefault("connection_timeout", "30000")));
            }
        }
    }
    
    /**
     * 加载音频配置
     */
    private void loadAudioConfig(Map<String, Object> audioConfig) {
        if (audioConfig != null) {
            this.audioConfig = new AudioConfig();
            this.audioConfig.setFrameSize((Integer) audioConfig.getOrDefault("frame_size", 4096));
            this.audioConfig.setMaxBufferSize((Integer) audioConfig.getOrDefault("max_buffer_size", 100));
            this.audioConfig.setSilenceThreshold((Double) audioConfig.getOrDefault("silence_threshold", 1000.0));
            this.audioConfig.setMinSilenceDuration((Integer) audioConfig.getOrDefault("min_silence_duration", 500));
            this.audioConfig.setRecognitionInterval((Integer) audioConfig.getOrDefault("recognition_interval", 2000));
            // 新增：目标 RMS（用于归一化增强）
            Object trms = audioConfig.get("target_rms");
            if (trms instanceof Number) {
                this.audioConfig.setTargetRms(((Number) trms).doubleValue());
            } else if (trms instanceof String) {
                try { this.audioConfig.setTargetRms(Double.parseDouble((String) trms)); } catch (Exception ignored) {}
            }
            // 断句优化：识别冷却与最大整句时长
            Object minGap = audioConfig.get("min_gap_between_recognitions_ms");
            if (minGap instanceof Number) {
                this.audioConfig.setMinGapBetweenRecognitionsMillis(((Number) minGap).intValue());
            } else if (minGap instanceof String) {
                try { this.audioConfig.setMinGapBetweenRecognitionsMillis(Integer.parseInt((String) minGap)); } catch (Exception ignored) {}
            }
            Object maxSeg = audioConfig.get("max_segment_duration_ms");
            if (maxSeg instanceof Number) {
                this.audioConfig.setMaxSegmentDurationMillis(((Number) maxSeg).intValue());
            } else if (maxSeg instanceof String) {
                try { this.audioConfig.setMaxSegmentDurationMillis(Integer.parseInt((String) maxSeg)); } catch (Exception ignored) {}
            }
        }
    }
    
    /**
     * 加载日志配置
     */
    private void loadLogConfig(Map<String, Object> logConfig) {
        if (logConfig != null) {
            this.logConfig = new LogConfig();
            this.logConfig.setLogLevel((String) logConfig.getOrDefault("level", "INFO"));
            this.logConfig.setLogFile((String) logConfig.getOrDefault("file", "logs/voice-comm.log"));
            this.logConfig.setMaxFileSize((String) logConfig.getOrDefault("max_file_size", "10MB"));
            this.logConfig.setMaxHistory((Integer) logConfig.getOrDefault("max_history", 30));
        }
    }

    /**
     * 加载台站配置
     */
    private void loadStationConfig(Map<String, Object> stationConfig) {
        if (stationConfig != null) {
            this.myCallsign = (String) stationConfig.getOrDefault("my_callsign", this.myCallsign);
        }
    }
    
    /**
     * 加载系统配置
     */
    private void loadSystemConfig(Map<String, Object> systemConfig) {
        if (systemConfig != null) {
            this.disableDatabase = (Boolean) systemConfig.getOrDefault("disable_database", this.disableDatabase);
        }
    }
    
    // Getter和Setter方法
    public String getBaiduAppId() {
        return baiduAppId;
    }
    
    public void setBaiduAppId(String baiduAppId) {
        this.baiduAppId = baiduAppId;
    }
    
    public String getBaiduApiKey() {
        return baiduApiKey;
    }
    
    public void setBaiduApiKey(String baiduApiKey) {
        this.baiduApiKey = baiduApiKey;
    }
    
    public String getBaiduSecretKey() {
        return baiduSecretKey;
    }
    
    public void setBaiduSecretKey(String baiduSecretKey) {
        this.baiduSecretKey = baiduSecretKey;
    }
    
    public DatabaseConfig getDatabaseConfig() {
        return databaseConfig;
    }
    
    public void setDatabaseConfig(DatabaseConfig databaseConfig) {
        this.databaseConfig = databaseConfig;
    }
    
    public AudioConfig getAudioConfig() {
        return audioConfig;
    }
    
    public void setAudioConfig(AudioConfig audioConfig) {
        this.audioConfig = audioConfig;
    }
    
    public LogConfig getLogConfig() {
        return logConfig;
    }
    
    public void setLogConfig(LogConfig logConfig) {
        this.logConfig = logConfig;
    }

    public String getMyCallsign() {
        return myCallsign;
    }

    public void setMyCallsign(String myCallsign) {
        this.myCallsign = myCallsign;
    }
    
    public boolean isDisableDatabase() {
        return disableDatabase;
    }
    
    public void setDisableDatabase(boolean disableDatabase) {
        this.disableDatabase = disableDatabase;
    }
    
    /**
     * 验证配置是否完整
     * 
     * @return true如果配置完整，false否则
     */
    public boolean isValid() {
        boolean valid = true;
        
        if (baiduAppId == null || baiduAppId.trim().isEmpty()) {
            logger.error("百度AI App ID 未配置");
            valid = false;
        }
        
        if (baiduApiKey == null || baiduApiKey.trim().isEmpty()) {
            logger.error("百度AI API Key 未配置");
            valid = false;
        }
        
        if (baiduSecretKey == null || baiduSecretKey.trim().isEmpty()) {
            logger.error("百度AI Secret Key 未配置");
            valid = false;
        }
        
        if (databaseConfig == null) {
            logger.error("数据库配置未设置");
            valid = false;
        }
        
        if (myCallsign == null || myCallsign.trim().isEmpty()) {
            logger.error("台站呼号 station.my_callsign 未配置");
            valid = false;
        }

        return valid;
    }
    
    /**
     * 音频配置类
     */
    public static class AudioConfig {
        private int frameSize = 4096;
        private int maxBufferSize = 100;
        private double silenceThreshold = 1000.0;
        private int minSilenceDuration = 500;
        private int recognitionInterval = 2000;
        // VAD与分段参数
        private double vadEnergyThreshold = 1200.0; // 能量门限，小于则视为无语音
        private int minSpeechDuration = 400; // 最小语音段时长(ms)，短于此不识别
        private boolean segmentOnSilence = true; // 是否在静音边界触发识别
        // 音频增强：目标 RMS（0 表示不做归一化）
        private double targetRms = 3000.0;
        // 断句优化：两次识别最小间隔与最大整句时长（毫秒）
        private int minGapBetweenRecognitionsMillis = 2000;
        private int maxSegmentDurationMillis = 9000;
        
        // Getter和Setter方法
        public int getFrameSize() {
            return frameSize;
        }
        
        public void setFrameSize(int frameSize) {
            this.frameSize = frameSize;
        }
        
        public int getMaxBufferSize() {
            return maxBufferSize;
        }
        
        public void setMaxBufferSize(int maxBufferSize) {
            this.maxBufferSize = maxBufferSize;
        }
        
        public double getSilenceThreshold() {
            return silenceThreshold;
        }
        
        public void setSilenceThreshold(double silenceThreshold) {
            this.silenceThreshold = silenceThreshold;
        }
        
        public int getMinSilenceDuration() {
            return minSilenceDuration;
        }
        
        public void setMinSilenceDuration(int minSilenceDuration) {
            this.minSilenceDuration = minSilenceDuration;
        }
        
        public int getRecognitionInterval() {
            return recognitionInterval;
        }
        
        public void setRecognitionInterval(int recognitionInterval) {
            this.recognitionInterval = recognitionInterval;
        }

        public double getVadEnergyThreshold() { return vadEnergyThreshold; }

        public void setVadEnergyThreshold(double vadEnergyThreshold) { this.vadEnergyThreshold = vadEnergyThreshold; }

        public int getMinSpeechDuration() { return minSpeechDuration; }

        public void setMinSpeechDuration(int minSpeechDuration) { this.minSpeechDuration = minSpeechDuration; }

        public boolean isSegmentOnSilence() { return segmentOnSilence; }

        public void setSegmentOnSilence(boolean segmentOnSilence) { this.segmentOnSilence = segmentOnSilence; }

        public double getTargetRms() { return targetRms; }

        public void setTargetRms(double targetRms) { this.targetRms = targetRms; }

        public int getMinGapBetweenRecognitionsMillis() { return minGapBetweenRecognitionsMillis; }

        public void setMinGapBetweenRecognitionsMillis(int minGapBetweenRecognitionsMillis) { this.minGapBetweenRecognitionsMillis = minGapBetweenRecognitionsMillis; }

        public int getMaxSegmentDurationMillis() { return maxSegmentDurationMillis; }

        public void setMaxSegmentDurationMillis(int maxSegmentDurationMillis) { this.maxSegmentDurationMillis = maxSegmentDurationMillis; }
    }
    
    /**
     * 日志配置类
     */
    public static class LogConfig {
        private String logLevel = "INFO";
        private String logFile = "logs/voice-comm.log";
        private String maxFileSize = "10MB";
        private int maxHistory = 30;
        
        // Getter和Setter方法
        public String getLogLevel() {
            return logLevel;
        }
        
        public void setLogLevel(String logLevel) {
            this.logLevel = logLevel;
        }
        
        public String getLogFile() {
            return logFile;
        }
        
        public void setLogFile(String logFile) {
            this.logFile = logFile;
        }
        
        public String getMaxFileSize() {
            return maxFileSize;
        }
        
        public void setMaxFileSize(String maxFileSize) {
            this.maxFileSize = maxFileSize;
        }
        
        public int getMaxHistory() {
            return maxHistory;
        }
        
        public void setMaxHistory(int maxHistory) {
            this.maxHistory = maxHistory;
        }
    }
}
